home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / zcomposite.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  10.0 KB  |  425 lines

  1. #include <stdlib.h>
  2. #include <GL/glut.h>
  3.  
  4. /*
  5. ** Create a single component texture map
  6. */
  7. GLfloat *make_texture(int maxs, int maxt)
  8. {
  9.     int s, t;
  10.     static GLfloat *texture;
  11.  
  12.     texture = (GLfloat *)malloc(maxs * maxt * sizeof(GLfloat));
  13.     for(t = 0; t < maxt; t++) {
  14.     for(s = 0; s < maxs; s++) {
  15.         texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1);
  16.     }
  17.     }
  18.     return texture;
  19. }
  20.  
  21. GLboolean stencil = GL_TRUE;
  22.  
  23. /* ARGSUSED1 */
  24. void key(unsigned char key, int x, int y)
  25. {
  26.     switch(key) {
  27.     case 't': /* toggle using stencil */
  28.       if(stencil == GL_TRUE)
  29.     stencil = GL_FALSE;
  30.       else
  31.     stencil = GL_TRUE;
  32.       glutPostRedisplay();
  33.       break;
  34.     case '\033':
  35.       exit(0);
  36.       break;
  37.     }
  38. }
  39.  
  40. enum {SPHERE = 1, CONE};
  41. enum {X, Y, Z};
  42.  
  43. int startx, starty;
  44. int wid, ht;
  45. int oldwid = 0, oldht = 0;
  46.  
  47. const int WINDIM = 512;
  48. const GLfloat FRUSTDIM = 110.f;
  49. const GLfloat FRUSTNEAR = 320.f;
  50. const GLfloat FRUSTFAR = 540.f;
  51. const GLfloat FRUSTDIFF = 540.f - 320.f;
  52.  
  53. GLboolean drawmode = GL_FALSE;
  54. GLboolean depthmode = GL_FALSE;
  55. GLboolean rubberbandmode = GL_FALSE;
  56. GLfloat *color;
  57. GLfloat *depth;
  58. GLfloat depthbias = 0.f;
  59. GLfloat raspos[] = {0.f, 0.f, -430.f};
  60.  
  61.  
  62. int winWidth = 512;
  63. int winHeight = 512;
  64.  
  65. GLfloat sx = 0;
  66. GLfloat sy = 0;
  67.  
  68.  
  69. /* Overlay Stuff */
  70. int transparent;
  71. int red;
  72.  
  73. void
  74. setRasterPosXY(int x, int y)
  75. {
  76.       raspos[X] = (x - winWidth/2) * sx;
  77.       raspos[Y] = (y - winHeight/2) * sy;
  78.  
  79.       glRasterPos3fv(raspos);
  80.  
  81.       glutPostRedisplay();
  82. }
  83.  
  84. void
  85. setRasterPosZ(int y)
  86. {
  87.       raspos[Z] = -(FRUSTNEAR + y * FRUSTDIFF/winHeight);
  88.  
  89.       depthbias = (y - winHeight/2.f)/winHeight;
  90.  
  91.       glRasterPos3fv(raspos);
  92.  
  93.       glutPostRedisplay();
  94. }
  95.  
  96.  
  97.  
  98. void
  99. motion(int x, int y)
  100. {
  101.   y = winHeight - y;
  102.   if(drawmode)
  103.     setRasterPosXY(x, y);
  104.  
  105.   if(rubberbandmode) {
  106.     wid = x - startx;
  107.     ht = y - starty;
  108.     glutPostOverlayRedisplay();
  109.   }
  110.  
  111.   if(depthmode)
  112.      setRasterPosZ(y);
  113. }
  114.  
  115. /* redraw function for overlay: used to show selected region */
  116. void
  117. overlay(void)
  118. {
  119.   if(glutLayerGet(GLUT_OVERLAY_DAMAGED)) {
  120.     glClear(GL_COLOR_BUFFER_BIT);
  121.   } else {
  122.     glIndexi(transparent);
  123.     glBegin(GL_LINE_LOOP);
  124.     glVertex2i(startx, starty);
  125.     glVertex2i(startx + oldwid, starty);
  126.     glVertex2i(startx + oldwid, starty + oldht);
  127.     glVertex2i(startx, starty + oldht);
  128.     glEnd();
  129.   }
  130.  
  131.   glIndexi(red);
  132.   glBegin(GL_LINE_LOOP);
  133.   glVertex2i(startx, starty);
  134.   glVertex2i(startx + wid, starty);
  135.   glVertex2i(startx + wid, starty + ht);
  136.   glVertex2i(startx, starty + ht);
  137.   glEnd();
  138.  
  139.   oldwid = wid;
  140.   oldht = ht;
  141.  
  142.   glFlush();
  143. }
  144.  
  145.  
  146. /* used to get current width and height of viewport */
  147. void
  148. reshape(int wid, int ht)
  149. {
  150.   glutUseLayer(GLUT_OVERLAY);
  151.   glMatrixMode(GL_PROJECTION);
  152.   glLoadIdentity();
  153.   gluOrtho2D(0, wid, 0, ht); /* 1 to 1 with window */
  154.   glMatrixMode(GL_MODELVIEW);
  155.   glViewport(0, 0, wid, ht);
  156.  
  157.   glutUseLayer(GLUT_NORMAL);
  158.   glViewport((GLint) (-wid * .1), (GLint) (-ht * .1),
  159.     (GLsizei) (wid * 1.2), (GLsizei) (ht * 1.2));
  160.  
  161.   winWidth = wid;
  162.   winHeight = ht;
  163.  
  164.   sx = 2 * FRUSTDIM/(winWidth * 1.2);
  165.   sy = 2 * FRUSTDIM/(winHeight * 1.2);
  166. }
  167.  
  168.  
  169. void
  170. mouse(int button, int state, int x, int y)
  171. {
  172.   y = winHeight - y; /* flip y orientation */
  173.   if(state == GLUT_DOWN)
  174.     switch(button) {
  175.     case GLUT_LEFT_BUTTON: /* select an image */
  176.       startx = x;
  177.       starty = y;
  178.       wid = 0; ht = 0;
  179.       rubberbandmode = GL_TRUE;
  180.       glutShowOverlay();
  181.       break;
  182.     case GLUT_MIDDLE_BUTTON:
  183.       glutUseLayer(GLUT_NORMAL);
  184.       if(color && depth) {
  185.       drawmode = GL_TRUE;
  186.       setRasterPosXY(x, y);
  187.       }
  188.       break;
  189.     case GLUT_RIGHT_BUTTON: /* change depth */
  190.       glutUseLayer(GLUT_NORMAL);
  191.       if(color && depth) {
  192.     depthmode = GL_TRUE;
  193.     setRasterPosZ(y);
  194.       }
  195.       break;
  196.     }
  197.   else /* GLUT_UP */
  198.     switch(button) {
  199.     case GLUT_LEFT_BUTTON:
  200.       rubberbandmode = GL_FALSE;
  201.       glutHideOverlay();
  202.       wid = x - startx;
  203.       ht = y - starty;
  204.       if(wid < 0) {
  205.     wid = -wid;
  206.     startx = x;
  207.       }
  208.       if(ht < 0) {
  209.     ht = -ht;
  210.     starty = y;
  211.       }
  212.       color = (GLfloat *)realloc(color, wid * ht * 3 * sizeof(GLfloat));
  213.       depth = (GLfloat *)realloc(depth, wid * ht * sizeof(GLfloat));
  214.  
  215.       glutUseLayer(GLUT_NORMAL);
  216.       glReadPixels(startx, starty, wid, ht, GL_RGB, GL_FLOAT, color);
  217.       glReadPixels(startx, starty, wid, ht, GL_DEPTH_COMPONENT, GL_FLOAT,
  218.            depth);
  219.       break;
  220.     case GLUT_MIDDLE_BUTTON:
  221.       drawmode = GL_FALSE;
  222.       break;
  223.     case GLUT_RIGHT_BUTTON: /* change depth */
  224.       depthmode = GL_FALSE;
  225.       break;
  226.     }
  227. }
  228.  
  229.  
  230. /* Called when window needs to be redrawn */
  231. void 
  232. redraw(void)
  233. {
  234.     /* material properties for objects in scene */
  235.     static GLfloat wall_mat[] = {1.f, 1.f, 1.f, 1.f};
  236.  
  237.     glutUseLayer(GLUT_NORMAL);    
  238.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
  239.  
  240.     /*
  241.     ** Note: wall verticies are ordered so they are all front facing
  242.     ** this lets me do back face culling to speed things up.
  243.     */
  244.  
  245.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
  246.  
  247.     /* floor */
  248.     /* make the floor textured */
  249.     glEnable(GL_TEXTURE_2D);
  250.  
  251.     /*
  252.     ** Since we want to turn texturing on for floor only, we have to
  253.     ** make floor a separate glBegin()/glEnd() sequence. You can't
  254.     ** turn texturing on and off between begin and end calls
  255.     */
  256.     glBegin(GL_QUADS);
  257.     glNormal3f(0.f, 1.f, 0.f);
  258.     glTexCoord2i(0, 0);
  259.     glVertex3f(-100.f, -100.f, -320.f);
  260.     glTexCoord2i(1, 0);
  261.     glVertex3f( 100.f, -100.f, -320.f);
  262.     glTexCoord2i(1, 1);
  263.     glVertex3f( 100.f, -100.f, -520.f);
  264.     glTexCoord2i(0, 1);
  265.     glVertex3f(-100.f, -100.f, -520.f);
  266.     glEnd();
  267.  
  268.     glDisable(GL_TEXTURE_2D);
  269.  
  270.     /* walls */
  271.  
  272.     glBegin(GL_QUADS);
  273.     /* left wall */
  274.     glNormal3f(1.f, 0.f, 0.f);
  275.     glVertex3f(-100.f, -100.f, -320.f);
  276.     glVertex3f(-100.f, -100.f, -520.f);
  277.     glVertex3f(-100.f,  100.f, -520.f);
  278.     glVertex3f(-100.f,  100.f, -320.f);
  279.  
  280.     /* right wall */
  281.     glNormal3f(-1.f, 0.f, 0.f);
  282.     glVertex3f( 100.f, -100.f, -320.f);
  283.     glVertex3f( 100.f,  100.f, -320.f);
  284.     glVertex3f( 100.f,  100.f, -520.f);
  285.     glVertex3f( 100.f, -100.f, -520.f);
  286.  
  287.     /* ceiling */
  288.     glNormal3f(0.f, -1.f, 0.f);
  289.     glVertex3f(-100.f,  100.f, -320.f);
  290.     glVertex3f(-100.f,  100.f, -520.f);
  291.     glVertex3f( 100.f,  100.f, -520.f);
  292.     glVertex3f( 100.f,  100.f, -320.f);
  293.  
  294.     /* back wall */
  295.     glNormal3f(0.f, 0.f, 1.f);
  296.     glVertex3f(-100.f, -100.f, -520.f);
  297.     glVertex3f( 100.f, -100.f, -520.f);
  298.     glVertex3f( 100.f,  100.f, -520.f);
  299.     glVertex3f(-100.f,  100.f, -520.f);
  300.     glEnd();
  301.  
  302.     glPushMatrix();
  303.     glTranslatef(-40.f, -60.f, -400.f);
  304.     glScalef(2, 2, 2);
  305.     glCallList(SPHERE);
  306.     glPopMatrix();
  307.  
  308.     glPushMatrix();
  309.     glTranslatef(50.f, -120.f, -400.f);
  310.     glScalef(2, 2, 2);
  311.     glCallList(CONE);
  312.     glPopMatrix();
  313.  
  314.     if(stencil) {
  315.       glEnable(GL_STENCIL_TEST);
  316.       glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  317.       glStencilFunc(GL_ALWAYS, 1, 1);
  318.       glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  319.       glPixelTransferf(GL_DEPTH_BIAS, depthbias);
  320.  
  321.       glDrawPixels(wid, ht, GL_DEPTH_COMPONENT, GL_FLOAT, depth);
  322.  
  323.       glPixelTransferf(GL_DEPTH_BIAS, 0.f);
  324.       glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  325.       glStencilFunc(GL_EQUAL, 1, 1);
  326.       glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  327.       glDisable(GL_DEPTH_TEST);
  328.  
  329.       glDrawPixels(wid, ht, GL_RGB, GL_FLOAT, color);
  330.  
  331.       glEnable(GL_DEPTH_TEST);
  332.       glDisable(GL_STENCIL_TEST);
  333.     } else
  334.       glDrawPixels(wid, ht, GL_RGB, GL_FLOAT, color);
  335.  
  336.     glutSwapBuffers();
  337. }
  338.  
  339.  
  340. const int TEXDIM = 256;
  341. /* Parse arguments, and set up interface between OpenGL and window system */
  342. main(int argc, char *argv[])
  343. {
  344.     GLfloat *tex;
  345.     static GLfloat lightpos[] = {50.f, 50.f, -320.f, 1.f};
  346.     static GLfloat sphere_mat[] = {1.f, .5f, 0.f, 1.f};
  347.     static GLfloat cone_mat[] = {0.f, .5f, 1.f, 1.f};
  348.     GLUquadricObj *sphere, *cone, *base;
  349.  
  350.     glutInit(&argc, argv);
  351.     glutInitWindowSize(WINDIM, WINDIM);
  352.  
  353.     glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL|GLUT_DOUBLE);
  354.     (void)glutCreateWindow("compositing images with depth");
  355.     glutDisplayFunc(redraw);
  356.     glutKeyboardFunc(key);
  357.     glutMouseFunc(mouse);
  358.     glutMotionFunc(motion);
  359.     glutReshapeFunc(reshape);
  360.  
  361.     /* draw a perspective scene */
  362.     glMatrixMode(GL_PROJECTION);
  363.     glFrustum(-FRUSTDIM, FRUSTDIM, -FRUSTDIM, FRUSTDIM, FRUSTNEAR, FRUSTFAR); 
  364.     glMatrixMode(GL_MODELVIEW);
  365.  
  366.     /* turn on features */
  367.     glEnable(GL_DEPTH_TEST);
  368.     glEnable(GL_LIGHTING);
  369.     glEnable(GL_LIGHT0);
  370.  
  371.     /* place light 0 in the right place */
  372.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  373.  
  374.     /* remove back faces to speed things up */
  375.     glCullFace(GL_BACK);
  376.  
  377.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  378.  
  379.     glNewList(SPHERE, GL_COMPILE);
  380.     /* make display lists for sphere and cone; for efficiency */
  381.     sphere = gluNewQuadric();
  382.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
  383.     gluSphere(sphere, 20.f, 20, 20);
  384.     gluDeleteQuadric(sphere);
  385.     glEndList();
  386.  
  387.     glNewList(CONE, GL_COMPILE);
  388.     cone = gluNewQuadric();
  389.     base = gluNewQuadric();
  390.     glRotatef(-90.f, 1.f, 0.f, 0.f);
  391.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
  392.     gluQuadricOrientation(base, GLU_INSIDE);
  393.     gluDisk(base, 0., 20., 20, 1);
  394.     gluCylinder(cone, 20., 0., 60., 20, 20);
  395.     gluDeleteQuadric(cone);
  396.     gluDeleteQuadric(base);
  397.     glEndList();
  398.  
  399.     /* load pattern for current 2d texture */
  400.     tex = make_texture(TEXDIM, TEXDIM);
  401.     glTexImage2D(GL_TEXTURE_2D, 0, 1, TEXDIM, TEXDIM, 0, GL_RED, GL_FLOAT, tex);
  402.     free(tex);
  403.  
  404.     /* storage for saved image */
  405.     color = 0;
  406.     depth = 0;
  407.     
  408.     glReadBuffer(GL_FRONT);/* so glReadPixel() always get the right image */
  409.  
  410.     glutInitDisplayMode(GLUT_SINGLE|GLUT_INDEX);
  411.     if(glutLayerGet(GLUT_OVERLAY_POSSIBLE)) {
  412.       glutEstablishOverlay();
  413.       glutHideOverlay();
  414.       transparent = glutLayerGet(GLUT_TRANSPARENT_INDEX);
  415.       glClearIndex(transparent);
  416.       red = (transparent + 1) % glutGet(GLUT_WINDOW_COLORMAP_SIZE);
  417.       glutSetColor(red, 1.0, 0.0, 0.0);  /* Red. */
  418.       glutOverlayDisplayFunc(overlay);
  419.     }
  420.  
  421.     glutMainLoop();
  422.  
  423.     return 0;
  424. }
  425.